www.gusucode.com > VC++ 虚拟桌面程序源码-源码程序 > VC++ 虚拟桌面程序源码-源码程序/code/VirtualDesktop/VirtualDesktop.cpp
//Download by http://www.NewXing.com #include <Windows.h> #include <Stdio.h> #include <Tchar.h> #include <Sddl.h> #include <Aclapi.h> #pragma comment(lib, "Advapi32.lib") #include <Commctrl.h> #pragma comment(lib,"Comctl32.lib") #include <Wfext.h> #include <Shlobj.h> #include "VirtualDesktop.h" #include "Resource.h" HINSTANCE g_hinst; HWND g_hMainDlg; HDESK g_ahDesktop[MAXDESKNUM]; HBITMAP g_ahBitmap[MAXDESKNUM]; LPTSTR g_aszDesktopName[MAXDESKNUM]; INT g_iSelectIndex; INT g_iCurrentIndex; BOOL g_bHide; HBITMAP g_hDrwBmp; WNDPROC g_lpfnStcWndFunc; //获取整个屏幕位图 HBITMAP GetScreenBitmap(LPCRECT lpRect = NULL, BOOL bCursor = FALSE, BOOL bLayered = FALSE) { HBITMAP hRetBitmap; //返回位图句柄 HBITMAP hOldBitmap; //之前的位图句柄 HDC hScrDC; //屏幕设备描述表 HDC hMemDC; //和内存设备描述表 RECT rtCatch; //选中的矩形 CURSORINFO curInfo; //鼠标信息 DWORD dwRop; //光栅操作代码 INT nWidth; //位图宽度 INT nHeight; //高度 INT xScrn; //屏幕宽度 INT yScrn; //屏幕高度 //返回位图句柄置NULL hRetBitmap = NULL; //获取屏幕尺寸 xScrn = GetSystemMetrics(SM_CXSCREEN); yScrn = GetSystemMetrics(SM_CYSCREEN); //判断矩形是否为NULL if(lpRect == NULL) { //全屏 rtCatch.left = 0; rtCatch.top = 0; rtCatch.right = xScrn; rtCatch.bottom = yScrn; } else { //确保选定区域是可见的 if(lpRect->left < 0) rtCatch.left = 0; else rtCatch.left = lpRect->left; if(lpRect->top < 0) rtCatch.top = 0; else rtCatch.top = lpRect->top; if(lpRect->right > xScrn) rtCatch.right = xScrn; else rtCatch.right = lpRect->right; if(lpRect->bottom > yScrn) rtCatch.bottom = yScrn; else rtCatch.bottom = lpRect->bottom; } //获取宽高 nWidth = rtCatch.right - rtCatch.left; nHeight = rtCatch.bottom - rtCatch.top; //判断矩形是否为空 if(!IsRectEmpty(&rtCatch)) { //获得屏幕DC hScrDC = GetDC(NULL); if(hScrDC) { //为屏幕设备描述表创建兼容的内存设备描述表 hMemDC = CreateCompatibleDC(hScrDC); if(hMemDC) { // 创建一个与屏幕设备描述表兼容的位图 hRetBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); if(hRetBitmap) { // 把新位图选到内存设备描述表中 hOldBitmap = (HBITMAP)SelectObject(hMemDC, hRetBitmap); //是否绘制分层窗口 dwRop = SRCCOPY | (bLayered ? CAPTUREBLT : 0); // 把屏幕设备描述表拷贝到内存设备描述表中 BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, rtCatch.left, rtCatch.top, dwRop); //是否绘制鼠标 if(bCursor) { //获取鼠标信息 curInfo.cbSize = sizeof(CURSORINFO); if(GetCursorInfo(&curInfo)) { //绘制鼠标图标 DrawIconEx(hMemDC, curInfo.ptScreenPos.x, curInfo.ptScreenPos.y, curInfo.hCursor, 0, 0, FALSE, NULL, DI_DEFAULTSIZE | DI_NORMAL); } } //得到屏幕位图的句柄 hRetBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); } DeleteDC(hMemDC); } ReleaseDC(NULL, hScrDC); } } return hRetBitmap; } //禁止64位文件系统重定向 BOOL MyWow64DisableWow64FsRedirection(PVOID *OldValue) { WOW64DISABLEWOW64FSREDIRECTION pfnWow64DisableWow64FsRedirection; if (!OldValue) return FALSE; pfnWow64DisableWow64FsRedirection = (WOW64DISABLEWOW64FSREDIRECTION)GetProcAddress( GetModuleHandle(_T("Kernel32.dll")), "Wow64DisableWow64FsRedirection"); if (!pfnWow64DisableWow64FsRedirection) return FALSE; return pfnWow64DisableWow64FsRedirection(OldValue); } //恢复64位文件系统重定向 BOOL MyWow64RevertWow64FsRedirection(PVOID OldValue) { WOW64REVERTWOW64FSREDIRECTION pfnWow64RevertWow64FsRedirection; if (!OldValue) return FALSE; pfnWow64RevertWow64FsRedirection = (WOW64REVERTWOW64FSREDIRECTION)GetProcAddress( GetModuleHandle(_T("Kernel32.dll")), "Wow64RevertWow64FsRedirection"); if (!pfnWow64RevertWow64FsRedirection) return FALSE; return pfnWow64RevertWow64FsRedirection(OldValue); } //在指定桌面启动进程 BOOL StartProcess(LPTSTR pszDesktopName, LPTSTR pszApplicationName) { STARTUPINFO si; PROCESS_INFORMATION piExplor; RtlZeroMemory(&si, sizeof(STARTUPINFO)); RtlZeroMemory(&piExplor, sizeof(PROCESS_INFORMATION)); si.cb = sizeof(STARTUPINFO); si.lpDesktop = pszDesktopName; if(!CreateProcess(pszApplicationName, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &piExplor) ) return FALSE; CloseHandle(piExplor.hThread); CloseHandle(piExplor.hProcess); return TRUE; } //打开所有桌面,并且初始化所有桌面名 VOID InitAllDesktop() { INT i; for(i=0; i<MAXDESKNUM; i++) { g_aszDesktopName[i] = new TCHAR[MAXDESKNAME]; if(i == 0) lstrcpy(g_aszDesktopName[i], _T("Default")); else wsprintf(g_aszDesktopName[i], _T("%s%d"), _T("Virtual"), i); g_ahDesktop[i] = OpenDesktop(g_aszDesktopName[i], 0, FALSE, GENERIC_ALL); } } //获取线程所在的桌面 INT GetCurrentDesktopIndex() { HDESK hThreadDesk; TCHAR szStr[MAXDESKNAME]; INT i; hThreadDesk = GetThreadDesktop(GetCurrentThreadId());//获取线程当前桌面 if(GetUserObjectInformation(hThreadDesk, UOI_NAME, szStr, sizeof(szStr), NULL))//获取桌面的名称 { for(i=0; i<MAXDESKNUM; i++) { if(lstrcmpi(szStr, g_aszDesktopName[i]) == 0) return i; } } return -1; } //关闭所有桌面,释放内存 VOID UnInitAllDesktop() { INT i; for(i=0; i<MAXDESKNUM; i++) { delete []g_aszDesktopName[i]; g_aszDesktopName[i] = NULL; if(g_ahDesktop[i]) { CloseDesktop(g_ahDesktop[i]); g_ahDesktop[i] = NULL; } } } //根据全局变量来决定启用或者禁用按钮 VOID EnableButton(HWND hDlg, HDESK *phDesktop) { INT i; HWND hWnd; for(i=0; i<MAXDESKNUM; i++) { hWnd = GetDlgItem(hDlg, IDC_DESKTOP0 + i); EnableWindow(hWnd, phDesktop[i] ? TRUE : FALSE); } } //静态控件的子类化 LRESULT CALLBACK ThumbStaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_PAINT://这里主要负责将位图缩小绘制 { HDC hDC; PAINTSTRUCT ps; RECT rect; HDC hMemDC; HBITMAP hOldBimap; BITMAP bitmap; HFONT hOldFont; INT iOldStretchMode; hDC = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rect); FillRect(hDC, &rect, GetSysColorBrush(COLOR_WINDOW));//填充为窗口色 if(g_hDrwBmp) { if(GetObject(g_hDrwBmp, sizeof(BITMAP), &bitmap)) { hMemDC = CreateCompatibleDC(hDC); hOldBimap = (HBITMAP)SelectObject(hMemDC, g_hDrwBmp); iOldStretchMode = SetStretchBltMode(hDC, HALFTONE); StretchBlt(hDC, rect.left, rect.top, rect.right, rect.bottom, hMemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); SetStretchBltMode(hDC, iOldStretchMode); SelectObject(hMemDC, hOldBimap); DeleteDC(hMemDC); } } else { SetBkMode(hDC, TRANSPARENT); hOldFont = (HFONT)SelectObject(hDC, GetStockObject(SYSTEM_FIXED_FONT)); DrawText(hDC, _T("该桌面还没有快照"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); SelectObject(hDC, hOldFont); SetBkMode(hDC, OPAQUE); } EndPaint(hWnd, &ps); } return FALSE; } return CallWindowProc(g_lpfnStcWndFunc, hWnd, uMsg, wParam, lParam); } INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static HWND s_hThumbStatic; switch (message) { case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hDlg, &ps); EndPaint(hDlg, &ps); } break; case WM_INITDIALOG: { HWND hwndFocus = (HWND) wParam; LPARAM lInitParam = lParam; SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_MAIN))); s_hThumbStatic = GetDlgItem(hDlg, IDC_STATIC_THUMB); SetDlgItemText(hDlg, IDC_EDIT_SELECT, g_aszDesktopName[g_iSelectIndex]);//设置选中桌面名 SetDlgItemText(hDlg, IDC_EDIT_CURRENT, g_aszDesktopName[g_iCurrentIndex]);//设置当前桌面名 g_hDrwBmp = g_ahBitmap[g_iSelectIndex];//当前选中位图 g_lpfnStcWndFunc = (WNDPROC)SetWindowLongPtr(s_hThumbStatic, GWLP_WNDPROC, (LONG_PTR)ThumbStaticWndProc);//子类化 EnableButton(hDlg, g_ahDesktop);//启用按钮 RegisterHotKey(hDlg, 1001, MOD_SHIFT | MOD_ALT ,'D');//注册热键 RegisterHotKey(hDlg, 1002, MOD_SHIFT | MOD_ALT ,'G'); RegisterHotKey(hDlg, 1003, MOD_SHIFT | MOD_ALT ,'H'); RegisterHotKey(hDlg, 1004, MOD_SHIFT | MOD_ALT ,'S'); } break; case WM_HOTKEY: { int idHotKey = (int) wParam; UINT fuModifiers = (UINT) LOWORD(lParam); UINT uVirtKey = (UINT) HIWORD(lParam); switch(idHotKey) { case 1001://切换到默认桌面 { if(g_iCurrentIndex == 0)//已经是默认桌面了 break; SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_DESKTOP0, 0), 0); SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_BTN_SWITCH, 0), 0); } break; case 1002://在已有的桌面来回切换 { INT nIndex; INT i; nIndex = g_iCurrentIndex; for(i=nIndex+1; i<10; i++) { if(g_ahDesktop[i]) break; } if(i == 10) { for(i=0; i<nIndex; i++) { if(g_ahDesktop[i]) break; } if(i == nIndex) break; } SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_DESKTOP0 + i, 0), 0); SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_BTN_SWITCH, 0), 0); } break; case 1003://隐藏窗体 { g_bHide = TRUE; ShowWindow(hDlg, SW_HIDE); } break; case 1004://显示窗体 { g_bHide = FALSE; ShowWindow(hDlg, SW_NORMAL); } break; } } break; case WM_COMMAND: { WORD wNotifyCode = HIWORD(wParam); WORD wID = LOWORD(wParam); HWND hwndCtl = (HWND) lParam; switch(wID) { case IDC_BTN_ABOUT: { MessageBox(hDlg, _T("本程序有以下快捷键,欢迎大家一起学习交流\r\n\r\n") _T("Shitf+Alt+D\t\t切换到默认桌面\r\n") _T("Shitf+Alt+G\t\t循环切换每个桌面\r\n") _T("Shitf+Alt+H\t\t隐藏窗体\r\n") _T("Shitf+Alt+S\t\t显示窗体\r\n"), _T("关于..."), MB_OK); } break; case IDC_BTN_SWITCH: { if(g_iSelectIndex == g_iCurrentIndex) { MessageBox(hDlg, _T("已经是该桌面了"), _T("提示"), MB_OK | MB_ICONINFORMATION); break; } SendMessage(hDlg, WM_CLOSE, 0, TRUE); } break; case IDC_BTN_SHELL: { PVOID pValue; if(GetShellWindow() == NULL)//判断是否存在Shell { MyWow64DisableWow64FsRedirection(&pValue); StartProcess(g_aszDesktopName[g_iCurrentIndex], _T("C:\\Windows\\Explorer.exe")); StartProcess(g_aszDesktopName[g_iCurrentIndex], _T("C:\\Windows\\System32\\ctfmon.exe")); MyWow64RevertWow64FsRedirection(pValue); } } break; case IDC_BTN_TASKMGR: { PVOID pValue; MyWow64DisableWow64FsRedirection(&pValue); StartProcess(g_aszDesktopName[g_iCurrentIndex], _T("C:\\Windows\\System32\\taskmgr.exe")); MyWow64RevertWow64FsRedirection(pValue); } break; case IDC_BTN_NEW: { INT i; for(i=0; i<10; i++) { if(i != 0 && !g_ahDesktop[i]) break; } if(i == 10) { MessageBox(hDlg, _T("由于桌面已满,无法新建桌面"), _T("错误"), MB_OK | MB_ICONERROR); break; } g_ahDesktop[i] = CreateDesktop( g_aszDesktopName[i], NULL, NULL, NULL, GENERIC_ALL, NULL); if(g_ahDesktop[i] == NULL) { MessageBox(hDlg, _T("创建桌面时发生错误,无法新建桌面"), _T("错误"), MB_OK | MB_ICONERROR); break; } EnableWindow(GetDlgItem(hDlg, IDC_DESKTOP0 + i), TRUE); } break; case IDC_DESKTOP0: case IDC_DESKTOP1: case IDC_DESKTOP2: case IDC_DESKTOP3: case IDC_DESKTOP4: case IDC_DESKTOP5: case IDC_DESKTOP6: case IDC_DESKTOP7: case IDC_DESKTOP8: case IDC_DESKTOP9: case IDC_DESKTOP10: case IDC_DESKTOP11: { g_iSelectIndex = wID - IDC_DESKTOP0; SetDlgItemText(hDlg, IDC_EDIT_SELECT, g_aszDesktopName[g_iSelectIndex]); g_hDrwBmp = g_ahBitmap[g_iSelectIndex]; InvalidateRect(s_hThumbStatic, NULL, TRUE); UpdateWindow(s_hThumbStatic); } break; } } break; case WM_SYSCOMMAND: { DWORD dwType = (DWORD)wParam; switch(dwType) { case SC_MINIMIZE: { MessageBox(hDlg, _T("使用快捷键Alt + Shift + S显示窗体"), _T("提示"), 0); g_bHide = TRUE; ShowWindow(hDlg, SW_HIDE); } return TRUE; } } break; case WM_NCPAINT: { if(g_bHide) ShowWindow(hDlg, SW_HIDE); } break; case WM_CLOSE: { EndDialog(hDlg, (INT_PTR)lParam); } break; } return FALSE; } DWORD WINAPI StartWindow( LPVOID lpParameter ) { TCHAR szMsg[512]; if(g_iSelectIndex < 0 || g_iSelectIndex >= MAXDESKNUM) { MessageBox(NULL, szMsg, _T("桌面选择不正确"), MB_OK | MB_ICONERROR); return 1; } if(!SetThreadDesktop(g_ahDesktop[g_iSelectIndex]))//设置线程桌面为选中的桌面 { wsprintf(szMsg, _T("无法设置线程桌面,错误:%d"), GetLastError()); MessageBox(NULL, szMsg, _T("错误"), MB_OK | MB_ICONERROR); return 1; } if(!SwitchDesktop(g_ahDesktop[g_iSelectIndex]))//切换到选中的桌面 { wsprintf(szMsg, _T("无法切换桌面,错误:%d"), GetLastError()); MessageBox(NULL, szMsg, _T("错误"), MB_OK | MB_ICONERROR); return 1; } g_iCurrentIndex = g_iSelectIndex; if(!DialogBox(g_hinst, (LPCTSTR)IDD_MAIN, NULL, MainDlgProc))//创建对话框 return 1; Sleep(100); if(g_ahBitmap[g_iCurrentIndex]) { DeleteObject(g_ahBitmap[g_iCurrentIndex]); } g_ahBitmap[g_iCurrentIndex] = GetScreenBitmap();//获取当前屏幕位图 return 0; } //主函数 int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) { HANDLE hMutex; HANDLE hThread; DWORD dwExitCode; g_hinst = hInstance; if (hMutex = CreateMutex(NULL, FALSE, _T("VirtualDesktop"))) { if (GetLastError() != ERROR_ALREADY_EXISTS) { InitAllDesktop(); if ((g_iSelectIndex = GetCurrentDesktopIndex()) == -1) { if(MessageBox(NULL, _T("检测到程序运行在一个无法识别的桌面,是否切换到默认桌面"), _T("提示"), MB_YESNO | MB_ICONQUESTION) == IDYES) { SwitchDesktop(g_ahDesktop[0]); } } else { do { dwExitCode = 1; hThread = CreateThread(NULL, NULL, StartWindow, NULL, NULL, NULL);//创建一个干净的线程 if(hThread) { WaitForSingleObject(hThread, INFINITE);//等待线程结束 GetExitCodeThread(hThread, &dwExitCode);//获取线程退出码 CloseHandle(hThread); } else { MessageBox(NULL, _T("创建线程失败"), _T("错误"), MB_OK | MB_ICONERROR); break; } } while(dwExitCode == 0); } UnInitAllDesktop(); } else { MessageBox(NULL, _T("程序只能运行一个实例"), _T("提示"), MB_OK | MB_ICONINFORMATION); } CloseHandle(hMutex); } else { MessageBox(NULL, _T("无法创建互斥体"), _T("错误"), MB_OK | MB_ICONERROR); return 1; } return 0; }